package com.sky.service.impl;

import com.sky.entity.Orders;
import com.sky.mapper.OrderDetailMapper;
import com.sky.mapper.OrderMapper;
import com.sky.mapper.UserMapper;
import com.sky.service.ReportService;
import com.sky.service.WorkSpaceService;
import com.sky.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;

@Service
@Slf4j
public class ReportServiceImpl implements ReportService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private WorkSpaceService workSpaceService;

    /**
     * 统计用户信息
     *
     * @param begin
     * @param end
     * @return
     */
    @Override
    public UserReportVO getUserReport(LocalDate begin, LocalDate end) {
        // 创建返回对象
        UserReportVO userReportVO = new UserReportVO();
        List<LocalDate> dateList = new ArrayList<>();
        List<Integer> totalUserList = new ArrayList<>();
        List<Integer> newUserList = new ArrayList<>();
        // 建立循环,查询每天的用户数据
        while (begin.isBefore(end.plusDays(1))) {
            // 查询截至当天总用户数量
            Integer totalUser = userMapper.countAfter(begin.plusDays(1).atStartOfDay());
            // 查询当天新增用户数据
            Integer newUser = userMapper.countBetween(begin.atStartOfDay(), begin.plusDays(1).atStartOfDay());

            // 判断数据为null则设置为0
            totalUser = totalUser == null ? 0 : totalUser;
            newUser = newUser == null ? 0 : newUser;

            // 将数据放入集合中
            dateList.add(begin);
            totalUserList.add(totalUser);
            newUserList.add(newUser);

            // 日期往后加一天
            begin = begin.plusDays(1);
        }
        // 将集合中的数据转换为字符串,封装到返回对象中
        userReportVO.setDateList(getList2String(dateList));
        userReportVO.setTotalUserList(getList2String(totalUserList));
        userReportVO.setNewUserList(getList2String(newUserList));
        // 返回
        return userReportVO;
    }

    /**
     * 统计订单信息
     *
     * @param begin
     * @param end
     * @return
     */
    @Override
    public OrderReportVO getOrderReport(LocalDate begin, LocalDate end) {
        // 创建返回对象
        OrderReportVO orderReportVO = new OrderReportVO();
        // 有效订单数
        Integer validOrderCount = 0;
        // 订单总数
        Integer totalOrderCount = 0;

        // 日期列表
        List<LocalDate> dateList = new ArrayList<>();
        // 有效订单数列表
        List<Integer> validOrderCountList = new ArrayList<>();
        // 订单数列表
        List<Integer> orderCountList = new ArrayList<>();

        // 建立循环,查询每天的用户数据
        while (begin.isBefore(end.plusDays(1))) {
            // 查询当天完成的订单数量
            Integer validCount = orderMapper.countByStatusAndDateTime(Orders.COMPLETED, begin.atStartOfDay(), begin.plusDays(1).atStartOfDay());
            // 查询当天总订单数量
            Integer totalCount = orderMapper.countByStatusAndDateTime(null, begin.atStartOfDay(), begin.plusDays(1).atStartOfDay());

            // 判断订单总数如果为null则设置为0
            validCount = validCount == null ? 0 : validCount;
            totalCount = totalCount == null ? 0 : totalCount;

            // 数据处理
            validOrderCount += validCount;
            totalOrderCount += totalCount;
            dateList.add(begin);
            validOrderCountList.add(validCount);
            orderCountList.add(totalCount);

            // 日期往后加一天
            begin = begin.plusDays(1);
        }
        // 将集合中的数据转换为字符串,封装到返回对象中
        orderReportVO.setDateList(getList2String(dateList));
        orderReportVO.setValidOrderCountList(getList2String(validOrderCountList));
        orderReportVO.setOrderCountList(getList2String(orderCountList));
        orderReportVO.setTotalOrderCount(totalOrderCount);
        orderReportVO.setValidOrderCount(validOrderCount);
        // 订单完成率 -- 如果总订单数为0则返回0.0
        if (totalOrderCount == 0) {
            orderReportVO.setOrderCompletionRate(0.0);
            return orderReportVO;
        }
        // 订单完成率 -- 保留小数点后两位
        Double orderCompletionRate = validOrderCount / (double) totalOrderCount;
        BigDecimal completedRateBigDecimal = new BigDecimal(orderCompletionRate).setScale(2, RoundingMode.HALF_UP);

        orderReportVO.setOrderCompletionRate(completedRateBigDecimal.doubleValue());
        // 返回
        return orderReportVO;
    }

    /**
     * 统计营业额信息
     *
     * @param begin
     * @param end
     * @return
     */
    @Override
    public TurnoverReportVO getTurnoverReport(LocalDate begin, LocalDate end) {
        // 创建返回对象
        TurnoverReportVO turnoverReportVO = new TurnoverReportVO();
        List<LocalDate> dateList = new ArrayList<>();
        List<Double> turnoverList = new ArrayList<>();
        // 建立循环,查询每天的营业额数据
        while (begin.isBefore(end.plusDays(1))) {
            // 查询当天的总营业额
            Double turnover = orderMapper.sumAmountByStatusAndDateTime(Orders.COMPLETED, begin.atStartOfDay(), begin.plusDays(1).atStartOfDay());

            // 判断营业额为null则设置为0
            turnover = turnover == null ? 0 : turnover;

            // 将数据放入集合中
            dateList.add(begin);
            turnoverList.add(turnover);

            // 日期往后加一天
            begin = begin.plusDays(1);
        }
        // 将集合中的数据转换为字符串,封装到返回对象中
        turnoverReportVO.setDateList(getList2String(dateList));
        turnoverReportVO.setTurnoverList(getList2String(turnoverList));
        // 返回
        return turnoverReportVO;
    }

    /**
     * 统计销量排名
     *
     * @param begin
     * @param end
     * @return
     */
    @Override
    public SalesTop10ReportVO getSalesTop10(LocalDate begin, LocalDate end) {
        SalesTop10ReportVO salesTop10ReportVO = new SalesTop10ReportVO();
        List<String> nameList = new ArrayList<>();
        List<String> numberList = new ArrayList<>();
        // 查询销量排名
        List<SalesTop10ReportVO> list = orderDetailMapper
                .selectTop10(begin.atStartOfDay(), end.plusDays(1).atStartOfDay(),
                        10, Orders.COMPLETED);

        // 判断为null则返回空对象
        if (list == null || list.isEmpty()) {
            return salesTop10ReportVO;
        }

        // 封装到返回对象中
        for (SalesTop10ReportVO reportVO : list) {
            nameList.add(reportVO.getNameList());
            numberList.add(reportVO.getNumberList());
        }

        salesTop10ReportVO.setNameList(getList2String(nameList));
        salesTop10ReportVO.setNumberList(getList2String(numberList));
        return salesTop10ReportVO;
    }

    /**
     * 导出数据
     * @param response
     * @param begin
     * @param end
     */
    @Override
    public void export(HttpServletResponse response, LocalDateTime begin, LocalDateTime end) {
        // 查询营业数据
        // -- 概览数据
        BusinessDataVO businessData = workSpaceService.getBusinessData(begin, end);

        // 创建读取模板文件的输入流
        InputStream is = this.getClass().getClassLoader().getResourceAsStream("template/运营数据报表模板.xlsx");
        // 创建一个基于模板文件的工作簿对象
        try {
            XSSFWorkbook excel = new XSSFWorkbook(is);
            // 获取第一个sheet页
            XSSFSheet sheet = excel.getSheetAt(0);
            // 获取第4行 填充数据: 营业额 订单完成率 新增用户数
            XSSFRow row = sheet.getRow(3);
            row.getCell(2).setCellValue(businessData.getTurnover());
            row.getCell(4).setCellValue(businessData.getOrderCompletionRate());
            row.getCell(6).setCellValue(businessData.getNewUsers());
            // 获取第5行 填充数据: 有效订单 平均客单价
            row = sheet.getRow(4);
            row.getCell(2).setCellValue(businessData.getValidOrderCount());
            row.getCell(4).setCellValue(businessData.getUnitPrice());

            // 循环填充明细数据 从第8行开始填充
            int rowNum = 7;
            while (begin.isBefore(end)){
                businessData = workSpaceService.getBusinessData(begin, begin.plusDays(1));
                // 获取行数
                row = sheet.getRow(rowNum++);
                // 填充具体数据: 日期 营业额 订单总数 订单完成率 平均客单价 新增用户数
                row.getCell(1).setCellValue(begin.toLocalDate().toString());
                row.getCell(2).setCellValue(businessData.getTurnover());
                row.getCell(3).setCellValue(businessData.getValidOrderCount());
                row.getCell(4).setCellValue(businessData.getOrderCompletionRate());
                row.getCell(5).setCellValue(businessData.getUnitPrice());
                row.getCell(6).setCellValue(businessData.getNewUsers());
                // 日期往后加一天
                begin = begin.plusDays(1);
            }
            // 将文件下载到客户端浏览器
            ServletOutputStream os = response.getOutputStream();
            excel.write(os);
            // 关闭流
            os.close();
            excel.close();
            is.close();
        } catch (IOException e) {
            log.error("文件读取异常:{}",e.getMessage());
        }
    }

    // 将list集合转换为字符串,并使用逗号分隔
    private String getList2String(List list) {
        StringJoiner sj = new StringJoiner(",");
        for (Object o : list) {
            if (o == null) {
                sj.add("");
            } else {
                sj.add(o.toString());
            }
        }
        return sj.toString();
    }
}
